package com.samp.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 
 *中文数字工具类
 *
 */
public class CnNumUtils {
	
	  	//num 表示数字，lower表示小写，upper表示大写
		private static final String[] NUM_LOWER = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
		private static final String[] NUM_UPPER = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
		
		//unit 表示单位权值，lower表示小写，upper表示大写
		private static final String[] UNIT_LOWER = { "", "十", "百", "千" };
		private static final String[] UNIT_UPPER = { "", "拾", "佰", "仟"};
		private static final String[] UNIT_COMMON = {"","万", "亿","兆","京","垓","秭","穰","沟","涧","正","载"};
		
		//允许的格式
		private static final List<String> SUPPORT_TYPES = Arrays.asList("INTEGER","INT","LONG","DECIMAL","FLOAT","DOUBLE","STRING","BYTE","TYPE","SHORT");
		
		private static final String CN_DOT = "点";
		
		//中文数字
		private static final List<String> SUPPORT_CN_CHAR = Arrays.asList(NUM_LOWER);
		
		/**
		 * 数字转化为小写的汉字
		 * 
		 * @param num 将要转化的数字
		 * @return
		 */
		public static String toChineseLower(Object num){
			return format(num, NUM_LOWER, UNIT_LOWER);
		}
		
		/**
		 *  数字转化为大写的汉字
		 *  
		 * @param num 将要转化的数字
		 * @return
		 */
		public static String toChineseUpper(Object num){
			return format(num, NUM_UPPER, UNIT_UPPER);
		}
		
		public static void toNum(String chineseNum){
			if( chineseNum == null || "".equals(chineseNum.trim()) ){
				throw new RuntimeException("参数不能为空");
			}
			String[] splits = chineseNum.split(CN_DOT);
			if( splits.length > 2 ){
				throw new RuntimeException("格式错误，不能拆分成正确的整数和小数："+chineseNum);
			}
			
		}
		
		/**
		 * 处理整数部分
		 * @param intCnNum
		 */
		private static void processIntCnNum(String intCnNum){
			
		}
		
		/**
		 * 格式化数字
		 * 
		 * @param num			原数字
		 * @param numArray 	数字大小写数组
		 * @param unit			单位权值
		 * @return
		 */
		private static String format(Object num,String[] numArray,String[] unit){
			if(!SUPPORT_TYPES.contains(num.getClass().getSimpleName().toUpperCase())){
				throw new RuntimeException("不支持的格式类型");
			}
			//获取整数部分
			String intnum = getInt(String.valueOf(num));
			//获取小数部分
			String decimal = getFraction(String.valueOf(num));
			//格式化整数部分
			String result = formatIntPart(intnum,numArray,unit);
			if(!"".equals(decimal)){//小数部分不为空
				//格式化小数
				result += "点"+formatFractionalPart(decimal, numArray);
			}
			return result;
		}
		

		/**
		 * 获取整数部分
		 * 
		 * @param num
		 * @return
		 */
		private static String getInt(String num){
			//检查格式
			checkNum(num);
			
			char[] val = String.valueOf(num).toCharArray();
			StringBuffer sb = new StringBuffer();
			int t , s = 0;
			for (int i = 0; i < val.length; i++) {
				if(val[i]=='.') {
					break;
				}
				t = Integer.parseInt(val[i]+"",16);
				if(s+t==0){
					continue;
				}
				sb.append(t);
				s+=t;
			}
			return (sb.length()==0? "0":sb.toString());
		}

		/**
		 * 检查数字格式
		 * 
		 * @param num
		 */
		private static void checkNum(String num) {
			if(num.indexOf(".") != num.lastIndexOf(".")){
				throw new RuntimeException("数字["+num+"]格式不正确!");
			}
			if(num.indexOf("-") != num.lastIndexOf("-") || num.lastIndexOf("-")>0){
				throw new RuntimeException("数字["+num+"]格式不正确！");
			}
			if(num.indexOf("+") != num.lastIndexOf("+")){
				throw new RuntimeException("数字["+num+"]格式不正确！");
			}
			if(num.indexOf("+") != num.lastIndexOf("+")){
				throw new RuntimeException("数字["+num+"]格式不正确！");
			}
			if(num.replaceAll("[\\d|\\.|\\-|\\+]", "").length()>0){
				throw new RuntimeException("数字["+num+"]格式不正确！");
			}
		}

		/**
		 * 获取小数部分
		 * 
		 * @param num
		 * @return
		 */
		private static String getFraction(String num){
			int i = num.lastIndexOf(".");
			if(num.indexOf(".") != i){
				throw new RuntimeException("数字格式不正确，最多只能有一位小数点！");
			}
			String fraction =""; 
			if(i>=0){
				fraction = getInt(new StringBuffer(num).reverse().toString());
				if(fraction.equals("0")){
					return "";
				}
			}
			return new StringBuffer(fraction).reverse().toString();
		}
		
		/**
		 * 分割数字，每4位一组
		 * 
		 * @param num
		 * @return
		 */
		private static Integer[] split2IntArray(String num){
			String prev = num.substring(0,num.length() % 4);
			String stuff = num.substring(num.length() % 4);
			if(!"".equals(prev)){
				num = String.format("%04d",Integer.valueOf(prev))+stuff;
			}
			Integer[] ints = new Integer[num.length()/4];
			int idx=0;
			for(int i=0;i<num.length();i+=4){
				String n = num.substring(i,i+4);
				ints[idx++]=Integer.valueOf(n);
			}
			return ints;
		}
		
		/**
		 * 格式化整数部分
		 * 
		 * @param num	整数部分
		 * @param numArray 数字大小写数组
		 * @return
		 */
		private static String formatIntPart(String num,String[] numArray,String[] unit){
			
			//按4位分割成不同的组（不足四位的前面补0）
			Integer[] intnums = split2IntArray(num);

			boolean zero = false;
			StringBuffer sb = new StringBuffer();
			for(int i=0;i<intnums.length;i++){
				//格式化当前4位
				String r = formatInt(intnums[i], numArray,unit);
				if("".equals(r)){//
					if((i+1)==intnums.length){
						sb.append(numArray[0]);//结果中追加“零”
					}else{
						zero=true;
					}
				}else{//当前4位格式化结果不为空（即不为0）
					if(zero || (i>0 && intnums[i]<1000)){//如果前4位为0，当前4位不为0
						sb.append(numArray[0]);//结果中追加“零”
					}
					sb.append(r);
					sb.append(UNIT_COMMON[intnums.length-1-i]);//在结果中添加权值
					zero=false;
				}
			}
			return sb.toString();
		}

		/**
		 * 格式化小数部分
		 * 
		 * @param decimal 小数部分
		 * @param numArray 数字大小写数组
		 * @return
		 */
		private static String formatFractionalPart(String decimal,String[] numArray) {
			char[] val = String.valueOf(decimal).toCharArray();
			int len = val.length;
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < len; i++) {
				int n = Integer.valueOf(val[i] + "");
				sb.append(numArray[n]);
			}
			return sb.toString();
		}
		
		
		/**
		 * 格式化4位整数
		 * 
		 * @param num
		 * @param numArray
		 * @return
		 */
		private static String formatInt(int num,String[] numArray,String[] unit){
			char[] val = String.valueOf(num).toCharArray();
			int len = val.length;
			StringBuilder sb = new StringBuilder();
			boolean isZero = false;
			for (int i = 0; i < len; i++) {
				int n = Integer.valueOf(val[i] + "");//获取当前位的数值
				if (n==0) {
					isZero = true;
				} else {
					if (isZero) {
						sb.append(numArray[Integer.valueOf(val[i-1] + "")]);
					}
					sb.append(numArray[n]);
					sb.append(unit[(len - 1) - i]);
					isZero=false;
				}
			}
			return sb.toString();
		}
		
		public static void main(String[] args) {
			short s = 10;
			byte b1=10;
			char c='A';
			Object[] nums = {s, b1, c, 0, 1001, 100100001L, 21., 205.23F, 205.23D, "01000010", "1000000100105.0123", ".142", "20.00", "1..2", true};
			System.out.println("将任意数字转化为汉字(包括整数、小数以及各种类型的数字)");
			System.out.println("--------------------------------------------");
			for(Object num :nums){
				try{
					System.out.print("["+num.getClass().getSimpleName()+"]"+num);
					for(int i=0;i<25-String.valueOf(num+num.getClass().getSimpleName()).length();i+=4){
						System.out.print("\t");
					}
					System.out.print(" format:"+toChineseLower(num));
					System.out.println("【"+toChineseUpper(num)+"】");
				}catch(Exception e){
					System.out.println(" 错误信息："+e.getMessage());
				}
			}
		}

}
